package com.boot.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.boot.common.constant.GlobalVar;
import com.boot.common.constant.MessageConstant;
import com.boot.common.result.Result;
import com.boot.system.entity.SysDept;
import com.boot.system.entity.SysUser;
import com.boot.system.mapper.UserMapper;
import com.boot.system.service.DeptService;
import com.boot.system.service.UserCacheService;
import com.boot.system.service.UserService;
import com.boot.util.ConvertUtil;
import com.boot.util.SecurityUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, SysUser> implements UserService {

    private final PasswordEncoder passwordEncoder;

    private final UserCacheService userCacheService;

    private final DeptService deptService;

    @Override
    public Page<SysUser> getUserPage(Map<String, Object> queryParam) {
        // 参数构建
        int pageNum = (int) queryParam.getOrDefault("pageNum", 1);
        int pageSize = (int) queryParam.getOrDefault("pageSize", 10);
        // 查询条件
        QueryWrapper query = QueryWrapper.create().from(SysUser.class);
        if (ObjectUtil.isNotEmpty(queryParam.get("loginTime"))) {
            // 登录时间
            List<Object> timeList = ConvertUtil.objectToList(queryParam.get("loginTime"));
            query.between("login_time", DateUtil.parse(timeList.get(0) + " 00:00:00").getTime(), DateUtil.parse(timeList.get(1) + " 23:59:59").getTime());
        }
        if (ObjectUtil.isNotEmpty(queryParam.get("createTime"))) {
            // 创建时间
            List<Object> timeList = ConvertUtil.objectToList(queryParam.get("createTime"));
            query.between("create_time", DateUtil.parse(timeList.get(0) + " 00:00:00").getTime(), DateUtil.parse(timeList.get(1) + " 23:59:59").getTime());
        }
        // 模糊查询
        query.and(q -> q.and(SysUser::getUsername).like(queryParam.get("keywords"))
                        .or(SysUser::getNickname).like(queryParam.get("keywords"))
                        .or(SysUser::getEmail).like(queryParam.get("keywords"))
                        .or(SysUser::getPhone).like(queryParam.get("keywords")),
                ObjectUtil.isNotEmpty(queryParam.get("keywords")));
        if (ObjectUtil.isNotEmpty(queryParam.get("pid"))) {
            // PID
            query.and(SysUser::getPid).eq(queryParam.get("pid"));
        }
        if (queryParam.get("roles") != null) {
            // 角色
            List<Object> roles = ConvertUtil.objectToList(queryParam.get("roles"));
            if (!roles.isEmpty()) {
                query.and(q -> {
                    for (Object role : roles) {
                        q.or(SysUser::getRoles).like(role);
                    }
                });
            }
        }
        if (ObjectUtil.isNotEmpty(queryParam.get("deptId"))) {
            // 部门
            query.and(SysUser::getDeptId).eq(queryParam.get("deptId"));
        }
        if (ObjectUtil.isNotEmpty(queryParam.get("status"))) {
            // 状态
            query.and(SysUser::getStatus).eq(queryParam.get("status"));
        }
        if (ObjectUtil.isNotEmpty(queryParam.get("loginIp"))){
            // 登录IP
            query.and(SysUser::getLoginIp).eq(queryParam.get("loginIp"));
        }
        //过滤本身账号
        query.ne("username", SecurityUtil.getUsername());
        //排序设置
        query.orderBy((String) queryParam.getOrDefault("orderBy", "update_time desc, id desc"));
        Page<SysUser> page = this.page(new Page<>(pageNum, pageSize), query);
        page.getRecords().forEach(user -> {
            //移除敏感字段
            user.setPassword(null);
        });
        return page;
    }

    @Override
    public Result<?> addUser(Map<String, Object> dataParam) {
        if (dataParam.get("password") != null) {
            dataParam.put("password", passwordEncoder.encode(dataParam.get("password").toString()));
        }
        //判断账号是否已存在
        if (dataParam.get("username") != null) {
            SysUser sysUserTemp = this.mapper.selectByUsername(dataParam.get("username").toString());
            if (sysUserTemp != null) {
                //账号已存在
                return Result.error(MessageConstant.USERNAME_EXIST);
            }
        }
        //判断邮箱是否已存在
        if (dataParam.get("email") != null) {
            SysUser sysUserTemp = this.mapper.selectByEmail(dataParam.get("email").toString());
            if (sysUserTemp != null) {
                //邮箱已存在
                return Result.error(MessageConstant.EMAIL_EXIST);
            }
        }
        //判断手机号是否已存在
        if (dataParam.get("phone") != null) {
            SysUser sysUserTemp = this.mapper.selectByPhone(dataParam.get("phone").toString());
            if (sysUserTemp != null) {
                //手机号已存在
                return Result.error(MessageConstant.PHONE_EXIST);
            }
        }
        SysUser sysUser = ConvertUtil.mapToClass(dataParam, SysUser.class);
        //查询部门路径
        if (sysUser.getDeptId() != null && sysUser.getDeptId() > 0) {
            SysDept sysDept = deptService.getCache(sysUser.getDeptId(), null);
            if (sysDept != null){
                sysUser.setDeptTreePath(sysDept.getTreePath());
            }
        }

        sysUser.setCreateBy(SecurityUtil.getUid());
        sysUser.setCreateTime(GlobalVar.systemTime);
        sysUser.setUpdateBy(SecurityUtil.getUid());
        sysUser.setUpdateTime(GlobalVar.systemTime);
        return Result.success(this.save(sysUser));
    }

    @Override
    public Result<?> updateUser(Map<String, Object> dataParam) {
        if (dataParam.get("password") != null) {
            dataParam.put("password", passwordEncoder.encode(dataParam.get("password").toString()));
        }
        if (dataParam.get("username") != null || dataParam.get("email") != null || dataParam.get("phone") != null) {
            //查询原数据
            SysUser sysUser = this.getById(Long.valueOf(dataParam.get("id").toString()));
            //判断账号是否可以修改
            if (dataParam.get("username") != null && !dataParam.get("username").equals(sysUser.getUsername())) {
                SysUser sysUserTemp = this.mapper.selectByUsername((String) dataParam.get("username"));
                if (sysUserTemp != null) {
                    //账号已存在
                    return Result.error(MessageConstant.USERNAME_EXIST);
                }
                //更改账号之后，删除缓存
                userCacheService.deleteCacheUser(sysUser.getId());
            }
            //判断邮箱是否可以修改
            if (dataParam.get("email") != null && !dataParam.get("email").equals(sysUser.getEmail())) {
                SysUser sysUserTemp = this.mapper.selectByEmail((String) dataParam.get("email"));
                if (sysUserTemp != null) {
                    //邮箱已存在
                    return Result.error(MessageConstant.EMAIL_EXIST);
                }
            }
            //判断手机号是否可以修改
            if (dataParam.get("phone") != null && !dataParam.get("phone").equals(sysUser.getPhone())) {
                SysUser sysUserTemp = this.mapper.selectByPhone((String) dataParam.get("phone"));
                if (sysUserTemp != null) {
                    //手机号已存在
                    return Result.error(MessageConstant.PHONE_EXIST);
                }
            }
        }
        SysUser sysUser = ConvertUtil.mapToClass(dataParam, SysUser.class);
        //查询部门路径
        if (sysUser.getDeptId() != null && sysUser.getDeptId() > 0) {
            SysDept sysDept = deptService.getCache(sysUser.getDeptId(), null);
            if (sysDept != null){
                sysUser.setDeptTreePath(sysDept.getTreePath());
            }
        }
        sysUser.setUpdateBy(SecurityUtil.getUid());
        sysUser.setUpdateTime(GlobalVar.systemTime);
        boolean result = this.updateById(sysUser);
        if (result) {
            //更新缓存
            userCacheService.updateCacheUser(sysUser.getId());
        }
        return Result.success(result);
    }

    @Override
    public boolean deleteUser(String ids) {
        List<Long> idList = Arrays.stream(ids.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        //先删除缓存
        for (Long id : idList) {
            userCacheService.deleteCacheUser(id);
        }
        //数据库-逻辑删除
        return this.removeByIds(idList);
    }

    @Override
    public boolean updatePassword(Long userId, String password) {
        boolean result = this.update(
                new SysUser().setPassword(passwordEncoder.encode(password)),
                QueryWrapper.create().eq(SysUser::getId, userId)
        );
        if (result) {
            //更新缓存
            userCacheService.updateCacheUser(userId);
        }
        return result;
    }

    @Override
    public Result<?> changePassword(String oldPassword, String newPassword) {
        String username = SecurityUtil.getUsername();
        //验证用户是否存在
        SysUser sysUser = this.mapper.selectByUsername(username);
        if (sysUser == null) {
            return Result.error(MessageConstant.USERNAME_NOT_EXIST);
        }
        //验证码原密码是否正确
        if (!passwordEncoder.matches(oldPassword, sysUser.getPassword())) {
            return Result.error(MessageConstant.OLD_PASSWORD_ERROR);
        }
        return Result.success(updatePassword(sysUser.getId(), newPassword));
    }

    @Override
    public void updateUserStatus(String username, String email, String phone, Integer status) {
        QueryWrapper query = QueryWrapper.create().from(SysUser.class);
        if (username != null){
            query.eq(SysUser::getUsername, username);
        }
        if (email != null){
            query.eq(SysUser::getEmail, email);
        }
        if (phone != null){
            query.eq(SysUser::getPhone, phone);
        }
        this.update(new SysUser().setStatus(status), query);
    }

    @Override
    public void updateLoginIp(String username, String email, String phone, String ip) {
        QueryWrapper query = QueryWrapper.create().from(SysUser.class);
        if (username != null){
            query.eq(SysUser::getUsername, username);
        }
        if (email != null){
            query.eq(SysUser::getEmail, email);
        }
        if (phone != null){
            query.eq(SysUser::getPhone, phone);
        }
        this.update(new SysUser().setLoginIp(ip).setLoginTime(GlobalVar.systemTime), query);
    }

    @Override
    public SysUser login(String username, String email, String phone, String password) {
        QueryWrapper query = QueryWrapper.create().from(SysUser.class);
        if (username != null){
            query.eq(SysUser::getUsername, username);
        }
        if (email != null){
            query.eq(SysUser::getEmail, email);
        }
        if (phone != null){
            query.eq(SysUser::getPhone, phone);
        }
        query.eq(SysUser::getPassword, passwordEncoder.encode(password));
        return this.getOne(query);
    }

}